/***********************************************************************
 *            Project: CoreCms
 *        ProjectName: 核心内容管理系统                                
 *                Web: https://www.corecms.net                      
 *             Author: 大灰灰                                          
 *              Email: jianweie@163.com                                
 *         CreateTime: 2021/1/31 21:45:10
 *        Description: 暂无
 ***********************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.DTO.Distribution;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using SqlSugar;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 分销商订单记录表 接口实现
    /// </summary>
    public class CoreCmsDistributionOrderServices : BaseServices<CoreCmsDistributionOrder>, ICoreCmsDistributionOrderServices
    {
        private readonly ICoreCmsDistributionOrderRepository _dal;
        private readonly ICoreCmsUserServices _userServices;
        private readonly ICoreCmsDistributionServices _distributionServices;
        private readonly ICoreCmsOrderServices _orderServices;
        private readonly ICoreCmsOrderItemServices _orderItemServices;
        private readonly ICoreCmsProductsDistributionServices _productsDistributionServices;
        private readonly ICoreCmsProductsServices _productsServices;
        private readonly ICoreCmsUserBalanceServices _balanceServices;
        private readonly ICoreCmsGoodsServices _goodsServices;
        private readonly ICoreCmsDistributionOrderDetailsServices _distributionOrderDetailsServices;
        private readonly ICoreCmsSettingServices _settingServices;


        private readonly IUnitOfWork _unitOfWork;
        public CoreCmsDistributionOrderServices(IUnitOfWork unitOfWork, ICoreCmsDistributionOrderRepository dal, ICoreCmsDistributionServices distributionServices, ICoreCmsUserBalanceServices balanceServices, ICoreCmsOrderServices orderServices, ICoreCmsUserServices userServices, ICoreCmsOrderItemServices orderItemServices, ICoreCmsProductsDistributionServices productsDistributionServices, ICoreCmsProductsServices productsServices, ICoreCmsGoodsServices goodsServices, ICoreCmsDistributionOrderDetailsServices distributionOrderDetailsServices, ICoreCmsSettingServices settingServices)
        {
            this._dal = dal;
            _distributionServices = distributionServices;
            _balanceServices = balanceServices;
            _orderServices = orderServices;
            _userServices = userServices;
            _orderItemServices = orderItemServices;
            _productsDistributionServices = productsDistributionServices;
            _productsServices = productsServices;
            _goodsServices = goodsServices;
            _distributionOrderDetailsServices = distributionOrderDetailsServices;
            _settingServices = settingServices;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;
        }


        #region 重写根据条件查询分页数据
        /// <summary>
        ///     重写根据条件查询分页数据
        /// </summary>
        /// <param name="predicate">判断集合</param>
        /// <param name="orderByType">排序方式</param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="orderByExpression"></param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsDistributionOrder>> QueryPageAsync(Expression<Func<CoreCmsDistributionOrder, bool>> predicate,
            Expression<Func<CoreCmsDistributionOrder, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
            int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock);
        }
        #endregion


        #region 添加分销订单关联记录
        /// <summary>
        /// 添加分销订单关联记录
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> AddData(CoreCmsOrder order)
        {
            var jm = new WebApiCallBack();

            //查询获取几级返利
            var user = await _userServices.QueryByClauseAsync(p => p.id == order.userId);
            if (user is { parentId: > 0 })
            {
                //获取购物明细
                var orderItems = await _orderItemServices.QueryListByClauseAsync(p => p.orderId == order.orderId);
                var goodIds = orderItems.Select(p => p.goodsId).ToList();
                var productIds = orderItems.Select(p => p.productId).ToList();
                //获取货品数据
                var goods = await _goodsServices.QueryListByClauseAsync(p => goodIds.Contains(p.id));
                //获取货品数据
                var products = await _productsServices.QueryListByClauseAsync(p => productIds.Contains(p.id));
                //获取货品关联的分销数据
                var productsDistributions = await _productsDistributionServices.QueryListByClauseAsync(p => productIds.Contains(p.productsId));

                var allConfigs = await _settingServices.GetConfigDictionaries();
                var distributionLevel = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.DistributionLevel).ObjectToInt(0);

                await AddOther(order, orderItems, goods, products, productsDistributions, 1, user.parentId, distributionLevel); //本级是否返利
            }
            jm.status = true;

            return jm;
        }

        #endregion

        #region 循环插入上级

        /// <summary>
        /// 循环插入上级
        /// </summary>
        /// <param name="order">订单信息</param>
        /// <param name="orderItems"></param>
        /// <param name="goods"></param>
        /// <param name="products">订单货品</param>
        /// <param name="productsDistributions">货品分销数据</param>
        /// <param name="level">第几级</param>
        /// <param name="userId">用户id</param>
        /// <param name="distributionLevel">三级分销开启的层级</param>
        /// <returns></returns>
        private async Task AddOther(CoreCmsOrder order, List<CoreCmsOrderItem> orderItems, List<CoreCmsGoods> goods, List<CoreCmsProducts> products, List<CoreCmsProductsDistribution> productsDistributions, int level = 0, int userId = 0, int distributionLevel = 3)
        {
            var user = await _userServices.QueryByClauseAsync(p => p.id == userId);
            if (user != null)
            {
                var commission = await _distributionServices.GetGradeAndCommission(user.id);
                if (commission.status && commission.data != null) //不是分销商的，不返利。
                {
                    var ommissionDto = commission.data as DistributionDto;
                    //直返本级
                    decimal amount = 0;
                    var distributionOrderDetails = new List<CoreCmsDistributionOrderDetails>();

                    foreach (var item in orderItems)
                    {
                        var orderDetails = new CoreCmsDistributionOrderDetails();
                        orderDetails.distributionOrderId = 0;
                        orderDetails.orderId = order.orderId;
                        orderDetails.orderId = order.orderId;
                        orderDetails.productPrice = item.price;
                        orderDetails.amount = 0;
                        orderDetails.goodId = item.goodsId;
                        orderDetails.name = item.name;
                        orderDetails.addon = item.addon;
                        orderDetails.productId = item.productId;
                        orderDetails.productNums = item.nums;
                        orderDetails.promotionAmount = item.promotionAmount;
                        orderDetails.imageUrl = item.imageUrl;
                        orderDetails.remark = "";
                        orderDetails.createTime = DateTime.Now;

                        var good = goods.Find(p => p.id == item.goodsId);
                        if (good == null)
                        {
                            distributionOrderDetails.Add(orderDetails);
                            continue;
                        }
                        var product = products.Find(p => p.id == item.productId);
                        if (product == null)
                        {
                            distributionOrderDetails.Add(orderDetails);
                            continue;
                        }

                        decimal mathMoney = 0;

                        if (good.productsDistributionType == (int)GlobalEnumVars.ProductsDistributionType.Global)
                        {
                            if (ommissionDto == null)
                            {
                                distributionOrderDetails.Add(orderDetails);
                                continue;
                            }
                            //获取实际当前支付金额,减去优惠的金额
                            //var itemAmount = item.amount - item.promotionAmount;
                            //目前的业务已经去除过优惠了，所以佣金不需要再减去优惠计算，会导致佣金折上折
                            var itemAmount = item.amount;
                            //如果去掉优惠需要负了，就为0
                            if (itemAmount < 0) itemAmount = 0;

                            mathMoney = level switch
                            {
                                //一级分销
                                1 when ommissionDto.commission_1 != null => ommissionDto.commission_1.type ==
                                                                            (int)GlobalEnumVars
                                                                                .DistributionCommissiontype
                                                                                .COMMISSION_TYPE_FIXED
                                    ? ommissionDto.commission_1.discount
                                    : Math.Round(ommissionDto.commission_1.discount * itemAmount / 100, 2),
                                //二级分销
                                2 when ommissionDto.commission_2 != null => ommissionDto.commission_2.type ==
                                                                            (int)GlobalEnumVars
                                                                                .DistributionCommissiontype
                                                                                .COMMISSION_TYPE_FIXED
                                    ? ommissionDto.commission_2.discount
                                    : Math.Round(ommissionDto.commission_2.discount * itemAmount / 100, 2),
                                //三级分销
                                3 when ommissionDto.commission_3 != null => ommissionDto.commission_3.type ==
                                                                            (int)GlobalEnumVars
                                                                                .DistributionCommissiontype
                                                                                .COMMISSION_TYPE_FIXED
                                    ? ommissionDto.commission_3.discount
                                    : Math.Round(ommissionDto.commission_3.discount * itemAmount / 100, 2),
                                _ => mathMoney
                            };
                        }
                        else if (good.productsDistributionType == (int)GlobalEnumVars.ProductsDistributionType.Detail)
                        {
                            var productsDistribution = productsDistributions.Find(p => p.productsId == item.productId);
                            if (productsDistribution == null)
                            {
                                continue;
                            }

                            mathMoney = level switch
                            {
                                1 when productsDistribution.levelOne > 0 => Math.Round(
                                    productsDistribution.levelOne * item.nums, 2),
                                2 when productsDistribution.levelTwo > 0 => Math.Round(
                                    productsDistribution.levelTwo * item.nums, 2),
                                3 when productsDistribution.levelThree > 0 => Math.Round(
                                    productsDistribution.levelThree * item.nums, 2),
                                _ => mathMoney
                            };
                        }

                        amount += mathMoney;
                        orderDetails.amount = mathMoney;
                        distributionOrderDetails.Add(orderDetails);

                    }

                    if (amount > 0)
                    {
                        var iData = new CoreCmsDistributionOrder();
                        iData.userId = userId;
                        iData.buyUserId = order.userId;
                        iData.orderId = order.orderId;
                        iData.amount = amount;
                        iData.level = level;
                        iData.isSettlement = (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementNo;  //默认未结算
                        iData.isDelete = false;
                        //判断是否返利过,有历史记录直接更新
                        var commissOrder = await _dal.QueryByClauseAsync(p => p.userId == userId && p.orderId == order.orderId);
                        if (commissOrder != null)
                        {
                            commissOrder.updateTime = DateTime.Now;
                            commissOrder.userId = iData.userId;
                            commissOrder.buyUserId = iData.buyUserId;
                            commissOrder.orderId = iData.orderId;
                            commissOrder.amount = iData.amount;
                            commissOrder.level = iData.level;
                            commissOrder.isSettlement = iData.isSettlement;
                            commissOrder.isDelete = iData.isDelete;
                            await _dal.UpdateAsync(commissOrder);
                        }
                        else
                        {
                            iData.createTime = DateTime.Now;
                            iData.updateTime = DateTime.Now;

                            var id = await _dal.InsertAsync(iData);
                            if (id > 0 && distributionOrderDetails.Any())
                            {
                                distributionOrderDetails.ForEach(p =>
                                {
                                    p.distributionOrderId = id;
                                });
                                await _distributionOrderDetailsServices.InsertAsync(distributionOrderDetails);
                            }
                        }
                    }
                }
                if (user.parentId > 0 && level < distributionLevel)
                {
                    //返第二级
                    level++;
                    await AddOther(order, orderItems, goods, products, productsDistributions, level, user.parentId, distributionLevel);
                }
            }
        }

        #endregion

        #region 订单结算处理事件
        /// <summary>
        /// 订单结算处理事件
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> FinishOrder(string orderId)
        {
            var jm = new WebApiCallBack();

            var order = await _orderServices.QueryByClauseAsync(p => p.orderId == orderId && p.status == (int)GlobalEnumVars.OrderStatus.Complete);
            if (order == null)
            {
                jm.msg = "订单查询失败";
                return jm;
            }
            //更新
            var list = await _dal.QueryListByClauseAsync(p => p.orderId == orderId && p.isSettlement == (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementNo);
            if (list != null && list.Any())
            {
                //foreach (var item in list)
                //{
                //    //钱挪到会员余额里面
                //    var result = await _balanceServices.Change(item.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.Distribution,
                //         item.amount, item.orderId);
                //    if (!result.status)
                //    {

                //    }
                //}

                await foreach (var result in ChangeForEach(list))
                {
                    if (!result.status)
                    {
                        //日常日志处理。
                    }
                };

                await _dal.UpdateAsync(p => new CoreCmsDistributionOrder()
                {
                    isSettlement = (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementYes,
                    updateTime = DateTime.Now
                }, p => p.orderId == orderId && p.isSettlement == (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementNo);
            }

            return jm;
        }

        //使用迭代器
        private async IAsyncEnumerable<WebApiCallBack> ChangeForEach(List<CoreCmsDistributionOrder> list)
        {
            foreach (var item in list)
            {
                //钱挪到会员余额里面
                var result = await _balanceServices.Change(item.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.Distribution,
                    item.amount, item.orderId);

                yield return result;
            }
        }


        #endregion

        #region 作废订单
        /// <summary>
        /// 作废订单
        /// </summary>
        /// <param name="orderId">订单编号</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> CancleOrderByOrderId(string orderId)
        {
            var jm = new WebApiCallBack();

            var res = await _dal.UpdateAsync(p => new CoreCmsDistributionOrder() { isSettlement = (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementCancel },
                p => p.orderId == orderId && p.isSettlement == (int)GlobalEnumVars.DistributionOrderSettlementStatus.SettlementNo);
            if (res == false)
            {
                jm.msg = "该未结算的订单不存在";
                return jm;
            }
            jm.msg = "操作成功";
            jm.status = true;


            return jm;
        }
        #endregion


        #region 获取下级推广订单数量
        /// <summary>
        ///     获取下级推广订单数量
        /// </summary>
        /// <param name="parentId">父类序列</param>
        /// <param name="type">1获取1级，其他为2级,0为全部</param>
        /// <param name="thisMonth">显示当月</param>
        /// <returns></returns>
        public async Task<int> QueryChildOrderCountAsync(int parentId, int type = 1, bool thisMonth = false)
        {
            return await _dal.QueryChildOrderCountAsync(parentId, type, thisMonth);

        }
        #endregion


        #region 获取下级推广订单金额
        /// <summary>
        ///     获取下级推广订单金额
        /// </summary>
        /// <param name="parentId">父类序列</param>
        /// <param name="type">1获取1级，其他为2级,0为全部</param>
        /// <param name="thisMonth">显示当月</param>
        /// <returns></returns>
        public async Task<decimal> QueryChildOrderMoneySumAsync(int parentId, int type = 1, bool thisMonth = false)
        {

            return await _dal.QueryChildOrderMoneySumAsync(parentId, type, thisMonth);

        }
        #endregion
    }
}
